package com.chat.net;

import com.chat.entity.DataPackage;
import com.chat.entity.event.ChannelEvent;
import com.chat.net.socket.EventHandlerDrive;
import com.chat.net.socket.HandlerManager;
import com.chat.net.socket.ObjectChannelContext;
import com.chat.net.socket.SocketChannel;

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * socketClient
 * 基于单例模式
 */
public class SocketClient implements Runnable{

    private static SocketClient socketClient;
    HandlerManager handlerManager;
    STATUE status;
    Socket socket;
    String IP = "192.168.0.107";
    int PORT = 8801;

    Executor executor;

    SocketChannel socketChannel;

    ObjectChannelContext objectChannelContext;
    String token = null;

    @Override
    public void run() {
        status = STATUE.RUN;
        while(status==STATUE.RUN){
            try {
                if(socketChannel!=null)
                    handlerManager.handler(socketChannel);
                Thread.sleep(1000);

            } catch (IOException|ClassNotFoundException | InterruptedException e) {
                status = STATUE.DAMAGE;
                throw new RuntimeException(e);
            }
        }
    }

    public enum STATUE{
        INIT,
        RUN,
        DAMAGE,
        DEATH
    }
    EventHandlerDrive eventHandlerDrive;


    /**
     * 发送数据包并添加对应的事件
     * @param channelEvent
     */
    public synchronized void addChannelEvent(ChannelEvent channelEvent, DataPackage dataPackage) {
        dataPackage.setEventId(channelEvent.getId());
        if(token!=null)
            dataPackage.setToken(token);
        try {
            eventHandlerDrive.addEvent(channelEvent);
            objectChannelContext.writeObject(dataPackage);
        } catch (IOException|NullPointerException e) {
            e.printStackTrace();
        }
    }


    private SocketClient() {
        executor = Executors.newFixedThreadPool(16);

        executor.execute(new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    init();
                } catch (IOException | InterruptedException e) {
                    status = STATUE.DEATH;
                }
            }
        }));



    }

    public synchronized void init() throws IOException, InterruptedException {
        eventHandlerDrive = new EventHandlerDrive();
        socket = new Socket(IP,PORT);
        status = STATUE.INIT;
        handlerManager = new HandlerManager();
        handlerManager.addHandler(eventHandlerDrive);
        objectChannelContext = new ObjectChannelContext(socket);
        Thread thread = new Thread(objectChannelContext);
        executor.execute(thread);
        Thread.sleep(1000);
        socketChannel = new SocketChannel(objectChannelContext);

        //初始化完毕之后执行本身的RUN
        executor.execute(socketClient);
    }

    public static SocketClient getSocketClient() {
        if(socketClient==null||socketClient.status==STATUE.DAMAGE||socketClient.status == STATUE.DEATH) {
            socketClient = new SocketClient();
        }
        return socketClient;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Executor getExecutor() {
        return executor;
    }
}
